package com.lib.fastkit.http.ok;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.TimeUtils;


import com.lib.fastkit.http.ok.err.HttpException;
import com.lib.fastkit.http.ok.extension.FileProgressRequestBody;
import com.lib.fastkit.http.ok.extension.file.OnDownloadListener;
import com.lib.fastkit.http.ok.interceptor.CacheInterceptor;
import com.lib.fastkit.http.ok.interceptor.NetInterceptor;
import com.lib.fastkit.http.ok.interceptor.RequestInterceptor;
import com.lib.fastkit.utils.log.LogUtil;
import com.lib.fastkit.utils.num.NumUtil;
import com.lib.fastkit.utils.rsa.RsaAndAesUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


/**
 * Email 240336124@qq.com
 * Created by Darren on 2017/3/4.
 * Version 1.0
 * Description: OkHttp默认的引擎
 */
public class OkHttpEngine implements IHttpEngine {

    private static OkHttpClient mOkHttpClient;
    private static List<Call> callList = new ArrayList<>();
    private static final int TIME_OUT = 15;
    private static final String TAG = "网络请求路径======";
    private Handler mDelivery;


    public OkHttpEngine(Context context) {

        mDelivery = new Handler(Looper.getMainLooper());

//        mOkHttpClient = new OkHttpClient.Builder()
//                .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
//                .addInterceptor(new RequestInterceptor(RequestInterceptor.Level.ALL))
//                .addNetworkInterceptor(new CacheInterceptor())
//                .cache(new Cache(context.getCacheDir(), 10240 * 1024))
//                .build();

        mOkHttpClient = new OkHttpClient.Builder()
                .retryOnConnectionFailure(true)
                .writeTimeout(TIME_OUT, TimeUnit.SECONDS)
                .readTimeout(TIME_OUT, TimeUnit.SECONDS)
                .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
                .addInterceptor(new RequestInterceptor(RequestInterceptor.Level.ALL))
//                .sslSocketFactory(createSSLSocketFactory())
//                .hostnameVerifier(new TrustAllHostnameVerifier())
                .build();

    }


    /**
     * 组装post请求参数body
     */
    protected RequestBody appendBody(Map<String, Object> params) {
        MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM);
        addParams(builder, params);
        return builder.build();
    }

    // 添加参数
    private void addParams(MultipartBody.Builder builder, Map<String, Object> params) {
        if (params != null && !params.isEmpty()) {

            for (String key : params.keySet()) {
                Object value = params.get(key);
                if (value instanceof File) {
                    // 处理文件 --> Object File
                    File file = (File) value;
                    builder.addFormDataPart(key, file.getName(), RequestBody
                            .create(MediaType.parse(guessMimeType(file
                                    .getAbsolutePath())), file));
                } else if (value instanceof List) {
                    // 代表提交的是 List集合
                    try {
                        List<File> listFiles = (List<File>) value;
                        for (int i = 0; i < listFiles.size(); i++) {
                            // 获取文件
                            File file = listFiles.get(i);
                            builder.addFormDataPart(key + i, file.getName(), RequestBody
                                    .create(MediaType.parse(guessMimeType(file
                                            .getAbsolutePath())), file));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    builder.addFormDataPart(key, value + "");
                }
            }
        }
    }

    /**
     * 猜测文件类型
     */
    private String guessMimeType(String path) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String contentTypeFor = fileNameMap.getContentTypeFor(path);
        if (contentTypeFor == null) {
            contentTypeFor = "application/octet-stream";
        }
        return contentTypeFor;
    }

    @Override
    public void get(final Context context, String url, Map<String, Object> params, final EngineCallBack callBack) {


        url = HttpUtils.jointParams(url, params);

        Log.e(TAG, url);

        Request request = new Request.Builder()
//                .addHeader("Connection", "close")
//                .addHeader("Connection", "keep-alive")
                .url(url)
                .tag(context)
                .get()
                .build();


        Call call = mOkHttpClient.newCall(request);
        callList.add(call);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(final Call call, final IOException e) {

                mDelivery.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.onError(e);
                        if (callList.contains(call)) {
                            callList.remove(call);
                        }

                    }
                });
            }

            @Override
            public void onResponse(final Call call, final Response response) throws IOException {
                final String result = response.body().string();
                if (!"".equals(result)) {
                    LogUtil.e(result);

                    mDelivery.post(new Runnable() {
                        @Override
                        public void run() {
                            if (response.code() != 200) {
                                callBack.onError(new HttpException(response));
                            } else {
                                callBack.onSuccess(result);
                            }
                            if (callList.contains(call)) {
                                callList.remove(call);
                            }

                        }
                    });
                } else {
                    LogUtil.e("当前GET请求返回为空");
                }
            }
        });

    }

    @Override
    public void post(final Context context, String url, Map<String, Object> params, final EngineCallBack callBack) {
        final String jointUrl = HttpUtils.jointParams(url, params);  //打印
        Log.e(TAG, jointUrl);

        RequestBody requestBody = appendBody(params);

        final Request request = new Request.Builder()
//                .addHeader("Connection", "close")
//                .addHeader("Connection", "keep-alive")
                .url(url)
                .tag(context)
                .post(requestBody)
                .build();

        Call call = mOkHttpClient.newCall(request);
        callList.add(call);
        call.enqueue(
                new Callback() {
                    @Override
                    public void onFailure(final Call call, final IOException e) {

                        mDelivery.post(new Runnable() {
                            @Override
                            public void run() {
                                callBack.onError(e);

                                if (callList.contains(call)) {
                                    callList.remove(call);
                                }

                            }
                        });

                    }

                    @Override
                    public void onResponse(final Call call, final Response response) throws IOException {
                        final String result = response.body().string();
                        if (!"".equals(result)) {
                            LogUtil.e(result);

                            mDelivery.post(new Runnable() {
                                @Override
                                public void run() {

                                    if (response.code() != 200) {
                                        callBack.onError(new HttpException(response));
                                    } else {
                                        callBack.onSuccess(result);
                                    }

                                    if (callList.contains(call)) {
                                        callList.remove(call);
                                    }

                                }
                            });
                        } else {

                            LogUtil.e("当前POST请求返回为空");
                        }
                    }
                }
        );

    }


    public void cancel() {

        try {

            if (callList.size() > 0) {

                for (int i = 0; i < callList.size(); i++) {

                    if (i < 0) {
                        LogUtil.e("出现下标小于0的问题");
                        return;
                    } else {

                        final Call call = callList.get(i);

                        new Thread(new Runnable() {
                            @Override
                            public void run() {

                                call.cancel();
                                callList.remove(call);

                            }
                        }).start();

                    }


                }

//                for (final Call call : callList) {
//                    new Thread(new Runnable() {
//                        @Override
//                        public void run() {
//
//
//
//                            call.cancel();
//                            callList.remove(call);
//
//                        }
//                    }).start();
//
//                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    //自定义SS验证相关类
    private static class TrustAllCerts implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

    private static class TrustAllHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private static SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
        }
        return ssfFactory;
    }


}
